﻿#region Using

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

using GameCommon.ComponentInterfaces;

using Microsoft.Xna.Framework;

#endregion

namespace GameCommon.Components
{
    public class ComponentCollection : IEnumerable<GameComponent>
    {
        private readonly List<GameComponent> components;

        public ComponentCollection()
        {
            this.components = new List<GameComponent>();
        }

        public int Count
        {
            get
            {
                return this.components.Count;
            }
        }

        public GameComponent this[int i]
        {
            get
            {
                try
                {
                    return this.components[i];
                }
                catch (ArgumentOutOfRangeException)
                {
                    throw new IndexOutOfRangeException();
                }
            }
        }

        public GameComponent this[string id]
        {
            get
            {
                return this.components.FirstOrDefault(x => string.Equals(x.Id, id));
            }
        }

        IEnumerator<GameComponent> IEnumerable<GameComponent>.GetEnumerator()
        {
            return this.components.GetEnumerator();
        }

        public IEnumerator GetEnumerator()
        {
            return this.components.GetEnumerator();
        }

        public void Add(GameComponent component)
        {
            this.components.Add(component);
        }

        public void Remove(GameComponent component)
        {
            this.components.Remove(component);
        }

        public void RemoveAll(Predicate<GameComponent> predicate)
        {
            this.components.RemoveAll(predicate);
        }

        public void AddRange(IEnumerable<GameComponent> componentsToAdd)
        {
            this.components.AddRange(componentsToAdd);
        }

        public void Dispose()
        {
            foreach (var component in this.components)
            {
                component.Dispose();
            }
        }

        public void Update(GameTime gameTime)
        {
            foreach (var component in this.components.OfType<IUpdatable>())
            {
                component.Update(gameTime);
            }
        }

        public void Clear()
        {
            this.components.Clear();
        }
    }
}